﻿using Lrd.Permissions.Repository;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Lrd.Permissions
{
    public static class ModelBuilderExtenions
    {
        public static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface)
        {
            return assembly.GetTypes().Where(x => !x.IsAbstract && x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));
        }

        public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
        {
            var mappingTypes = assembly.GetMappingTypes(typeof(IEntityMappingConfiguration<,>));
            foreach (var config in mappingTypes.Select(Activator.CreateInstance).Cast<IEntityMappingConfiguration>())
            {
                config.Map(modelBuilder);
            }
        }

    }

    public interface IEntityManager
    {
        void Initialize();
        /// <summary>
        /// 获取指定上下文类型的实体配置注册信息
        /// </summary>
        /// <param name="dbContextType">数据上下文类型</param>
        /// <returns></returns>
        IEnumerable<IEntityMappingConfiguration> GetEntityRegisters(Type dbContextType);

        /// <summary>
        /// 获取 实体类所属的数据上下文类
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns>数据上下文类型</returns>
        Type GetDbContextTypeForEntity(Type entityType);
    }

    public class EntityManager : IEntityManager {
        private static  ConcurrentDictionary<Type, IEntityMappingConfiguration[]> _entityRegistersDict
           = new ConcurrentDictionary<Type, IEntityMappingConfiguration[]>();

        public Type GetDbContextTypeForEntity(Type entityType)
        {
            var dict = _entityRegistersDict;
            if (dict.Count == 0)
            {
                throw new Exception($"未发现任何数据上下文实体映射配置，请通过对各个实体继承基类“EntityMappingConfiguration<TEntity, TKey>”以使实体加载到上下文中");
            }

             return  _entityRegistersDict.Where(o => o.Value.Any(m => m.EntityType == entityType)).FirstOrDefault().Key;
       

            //throw new Exception($"无法获取实体类“{entityType}”的所属上下文类型，请通过继承基类“EntityMappingConfiguration<TEntity, TKey>”配置实体加载到上下文中");
        }

        public IEnumerable<IEntityMappingConfiguration> GetEntityRegisters(Type dbContextType)
        {
            return _entityRegistersDict.ContainsKey(dbContextType)? _entityRegistersDict[dbContextType]: Enumerable.Empty<IEntityMappingConfiguration>();
        }

        public void Initialize()
        {
            var dict = _entityRegistersDict;
   

            var types=  GetType().Assembly.GetMappingTypes(typeof(IEntityMappingConfiguration<,>));
            dict.Clear();
            var groups = types.Select(o => Activator.CreateInstance(o) as IEntityMappingConfiguration).ToList().GroupBy(m=>m.DbContextType);
            Type key;
            foreach (var group in groups)
            {
                key = group.Key ?? typeof(DefaultDbContext);
                var list = new List<IEntityMappingConfiguration>();
                if (group.Key == null || group.Key == typeof(DefaultDbContext))
                {
                    list.AddRange(group);
                }
                else
                {
                    list = group.ToList();
                }
                if (list.Count > 0)
                {
                    dict[key] = list.ToArray();
                }
            }
            _entityRegistersDict = dict;


        }
    }


}
